/*
*	5A A5 |  LEN   |  FUNC_CODE   |  DATA       |  9A 9B                          			
*	帧头	字节数		功能码       数据内容        帧尾
*
*主机（串口屏）和从机（控制板）通信帧格式如下：
*  帧头（两字节）+字节数（单字节）+功能码（单字节）+数据+帧尾（两字节）；
*  帧头：5AH A5H；
*  字节数：字节数位置后的所有字节总数，包括功能码、数据、帧尾等字节数；
*  功能码：不同的控制功能代码；
*  数据：需要发送的数据；
*  帧尾：9AH 9BH (非校验，此数据固定)；
*
*/

#include "ScreenHandle.h"
#include "MidUsart.h"
#include "AppInit .h"
#include "fault_list.h"
#include "exth_list.h"
#include "operation_list.h"
#include "evtqueue.h"
#include "time.h"
#include "RTm.h"
#include "para.h"
#include "DrvWdgt.h"
#include "SysRtimePara.h"




static void SendRecBuf(uint8_t *Buf, uint8_t num);


/**
*	装载帧头
*  Buf: 整个帧的起始位置
*  num：数据数量
*/
static void ScreenloadHead(uint8_t *Buf)
{
	*Buf 		= SCREEN_HEAD1;
	*(Buf +1) 	= SCREEN_HEAD2;
}

/**
*	装载帧尾
*  dataBuf: 存储数据内容的缓冲区
*  
*/
static void ScreenloadTail(uint8_t *tailBuf)
{
	*tailBuf  		= SCREEN_TAIL1;
	*(tailBuf + 1) 	= SCREEN_TAIL2;
}



/*  0x90 查询系统状态  */
void ScreenDataRcv()
{
    uint8_t RecBuf[18];
	
	ScreenloadHead(RecBuf);
   
    RecBuf[2]  = 0x0D;
    RecBuf[3]  = CMD_REQUEST_0X90;
			   
    RecBuf[4]  = st_RtRunPara.systemStatus; 				//系统状态 0：运行 1：故障 2：启动
    RecBuf[5]  = st_RtRunPara.exthStatus; 					//灭火器启动状态 0：启动 1：喷洒 2：暂停 3：结束 4：故障
    RecBuf[6]  = (st_RtRunPara.exthCountdown << 8); 		//倒计时高八位（范围0 ~ 65535）
    RecBuf[7]  = (st_RtRunPara.exthCountdown & 0XFF); 		//倒计时低八位（范围0 ~ 65535）
    RecBuf[8]  = (st_RtRunPara.pressValue << 8); 			//压力反馈高八位（范围0 ~ 65535）
    RecBuf[9]  = (st_RtRunPara.pressValue & 0XFF); 			//压力反馈低八位（范围0 ~ 65535）
    RecBuf[10] = st_RtRunPara.liquidLevel; 					//液位反馈（范围0 ~ 255）
    RecBuf[11] = st_RtRunPara.UN_DEV_STATUS.devStatus; 		//泵阀状态 bit0~1:水泵1状态 bit2~3:水泵2状态 bit4~5:球阀状态 bit6~7:刺破阀状态
    RecBuf[12] = st_RtRunPara.UN_EVENT_STATUS.eventStatus; 	//bit0：故障标志位 bit1：操作记录标志位 bit2：启动记录标志位
    RecBuf[13] = 0; 										//预留
    
	RecBuf[14] = 100; 										// 电池1电量/%
    RecBuf[15] = 100;  										// 电池2电量/%
	
	ScreenloadTail(&RecBuf[16]);
	
    //发送接口
    SendRecBuf(RecBuf, 18);
    
}


/* 查询 版本号 */
void ScreenVersionRcv()
{
    uint8_t RecBuf[10];
    ScreenloadHead(RecBuf);
    RecBuf[2] = 0x07;
    RecBuf[3] = CMD_ASK_VERSION_0X91;
    
    RecBuf[4] = Version[0];//版本号
    RecBuf[5] = Version[1];//版本号
    RecBuf[6] = Version[2];//版本号
    RecBuf[7] = Version[3];//预留
    
	ScreenloadTail(&RecBuf[8]);
   
    //发送接口
    SendRecBuf(RecBuf, 10);
}




/*  查询故障 */
void ScreenFaultRcv()
{
	EVT_T evt;
	struct tm_t  faultTime;
		
	RtFaultListRead(1, &evt);		// 取出 链表第一个实时故障
	RtFaultListDelet(evt);			// 将这个节点删掉，保证下次读取第一个节点，是链表的是下一个故障节点
	local_time(evt.time, &faultTime);
	DEBUG_LOG_INFO(DEBUG_LEVEL_2, " fault read  %d  \n", evt.time);

	uint8_t RecBuf[14];
    ScreenloadHead(RecBuf);
    RecBuf[2] = 0x0B;
    RecBuf[3] = CMD_ASK_FAULT_0X92;
	
    RecBuf[4] = faultTime.tm_year<<8;//故障日期高八位（年）
    RecBuf[5] = faultTime.tm_year & 0XFF;//故障日期第八位（年）
    RecBuf[6] = faultTime.tm_mon;//故障日期（月）
    RecBuf[7] = faultTime.tm_mday;//故障日期（日）
    RecBuf[8] = faultTime.tm_hour;//时
    RecBuf[9] = faultTime.tm_min;//分
    RecBuf[10] = faultTime.tm_sec;//秒
    RecBuf[11] = evt.stFaultEvt;//故障类型   
	
	ScreenloadTail(&RecBuf[12]);
   
    //发送接口
    SendRecBuf(RecBuf,14);
};

/*  查询 操作 */
void ScreenOperateRcv()
{
	EVT_T evt;
	struct tm_t  OperatTime;
	
	RtFaultListRead(1, &evt);		// 取出 链表第一个实时故障
	RtFaultListDelet(evt);			// 将这个节点删掉，保证下次读取第一个节点，是链表的是下一个故障节点
	local_time(evt.time, &OperatTime);
	DEBUG_LOG_INFO(DEBUG_LEVEL_2, " screen  operate read  %d  \n", evt.time);

    uint8_t RecBuf[14];
    ScreenloadHead(RecBuf);
    RecBuf[2] = 0x0B;
    RecBuf[3] = CMD_ASK_OPER_0X93;
	
	RecBuf[4] = OperatTime.tm_year<<8;//故障日期高八位（年）
    RecBuf[5] = OperatTime.tm_year & 0XFF;//故障日期第八位（年）
    RecBuf[6] = OperatTime.tm_mon;//故障日期（月）
    RecBuf[7] = OperatTime.tm_mday;//故障日期（日）
    RecBuf[8] = OperatTime.tm_hour;//时
    RecBuf[9] = OperatTime.tm_min;//分
    RecBuf[10] = OperatTime.tm_sec;//秒
    RecBuf[11] = evt.stFaultEvt;//故障类型   
	
    ScreenloadTail(&RecBuf[12]);
    //发送接口
    SendRecBuf(RecBuf,14);
};


/*  查询启动记录 */
void ScreenStartRcv()
{
	
	EVT_T evt;
	struct tm_t  exthTime;
		
	RtExthListRead(1, &evt);		// 取出 链表第一个实时故障
	RtExthListDelet(evt);			// 将这个节点删掉，保证下次读取第一个节点，是链表的是下一个故障节点
	local_time(evt.time, &exthTime);
	DEBUG_LOG_INFO(DEBUG_LEVEL_2, " screen exth read  %d  \n", evt.time);	
	
    uint8_t RecBuf[14];
		
    ScreenloadHead(RecBuf);
    RecBuf[2]  = 0x0B;
    RecBuf[3]  = CMD_ASK_EXTH_0X94;
			   
    RecBuf[4]  = exthTime.tm_year<<8;//故障日期高八位（年）
    RecBuf[5]  = exthTime.tm_year & 0XFF;//故障日期第八位（年）
    RecBuf[6]  = exthTime.tm_mon;//故障日期（月）
    RecBuf[7]  = exthTime.tm_mday;//故障日期（日）
    RecBuf[8]  = exthTime.tm_hour;//时
    RecBuf[9]  = exthTime.tm_min;//分
    RecBuf[10] = exthTime.tm_sec;//秒
    RecBuf[11] = evt.stFaultEvt;//故障类型   
 
    ScreenloadTail(&RecBuf[12]);
    //发送接口
    SendRecBuf(RecBuf, 14);
};


/* 灭火器配置 */
void ScreenFireCfgInfo()
{
    uint8_t RecBuf[11];
    ScreenloadHead(RecBuf);
    RecBuf[2] = 0;
    RecBuf[3] = CMD_EXTH_CONF_0X95;


    
    ScreenloadTail(&RecBuf[9]);
    //发送接口
    SendRecBuf(RecBuf, 11);
};


/*  清除 记录 */
void ScreenClearRecord(uint8_t *buf)
{
	#define CLEAR_FAULT			0x01
	#define CLEAR_OPERA 		0x02
	#define CLEAR_EXTH_MESG 	0x04
	
	uint8_t clearType = buf[4];
	uint8_t result = 0;
	
	if(clearType == CLEAR_FAULT)
	{
		//TO DO: 清除故障记录
		result = 1;		
	}
	else if(clearType == CLEAR_OPERA)
	{
		//TO DO: 清除操作记录
		result = 1;	
	}
	else if(clearType == CLEAR_EXTH_MESG)
	{
		//TO DO: 清除启动记录
		result = 1;	
	}
	else
	{
		return;
	}
	
	
    uint8_t RecBuf[9];
    ScreenloadHead(RecBuf);
    RecBuf[2] = 0x06;
    RecBuf[3] = CMD_CLEAR_MESSG_0X96;
    
    RecBuf[4] = clearType;//返回接收到的指令类型 1：清除故障记录 2：清除操作记录 4：清楚启动记录
    RecBuf[5] = result;//清除结果 0：失败 1：成功
    RecBuf[6] = 0;//预留

    ScreenloadTail(&RecBuf[7]);
    
    //发送接口
    SendRecBuf(RecBuf, 9);
};




/*  校对时间  */
void ScreenCheckTime(uint8_t *buf)
{
	struct tm_t  reaTime;
    uint8_t 	RecBuf[8];
	uint16_t 	year;
	uint8_t		mon, day, hour, min, second;
	
	year	= (buf[4]<<8)+(buf[5]);
	mon		= buf[6];
	day  	= buf[7];
	hour	= buf[8];
	min		= buf[9];
	second	= buf[10];
	
	reaTime.tm_year = year -1970;
	reaTime.tm_mon  = mon;	
	reaTime.tm_mday = day ;
	reaTime.tm_hour = hour;
	reaTime.tm_min  = min;	  
	reaTime.tm_sec  = second;
	    	
	SetRTime(sec_time(&reaTime));
		
    ScreenloadHead(RecBuf);
    RecBuf[2] = 0x05;
    RecBuf[3] = CMD_CHECK_TIME_0X97;
    
    RecBuf[4] = 1;//接收到配置指令 0：校准失败 1：校准成功
    RecBuf[5] = 0;//预留

    ScreenloadTail(&RecBuf[6]);
    
    //发送接口
    SendRecBuf(RecBuf, 8);
};



/*  ID配置  */
void ScreenIdConfig(uint8_t *buf)
{
    uint8_t RecBuf[8];
		
	pSysPara->ucCAN_ID = buf[4];
	
	ParaWrite();
	
	
    ScreenloadHead(RecBuf);
    RecBuf[2] = 0x05;
    RecBuf[3] = CMD_ID_CONF_0X98;
    
    RecBuf[4] = 1;//接收到配置指令 0：更改失败 1：更改成功
    RecBuf[5] = 0;//预留
    
	
	ScreenloadTail(&RecBuf[6]);
    
    //发送接口
    SendRecBuf(RecBuf, 8);
};



/* 复位设备  */
void ScreenReset(uint8_t *buf)
{
    uint8_t RecBuf[8];
	uint8_t result = 0;
	
	if(buf[4] == 0X01)
	{
		result = 0X01;
		DrvFwdgtInit(200,FWDGT_PSC_DIV64);// AFTER 300MS RESET		
	}
	
    ScreenloadHead(RecBuf);
    RecBuf[2] = 0x05;
    RecBuf[3] = CMD_DEV_RESET_0X99;
    
    RecBuf[4] = result;//接收到指令 1：接收到复位指令 other：无效指令
    RecBuf[5] = 0;//预留

    ScreenloadTail(&RecBuf[6]);
    
    //发送接口
    SendRecBuf(RecBuf, 8);
		
};





void ScreenCmdHandle(uint8_t *buf)
{
    switch (buf[3])
    {
        case CMD_REQUEST_0X90:
			
            ScreenDataRcv();     //数据回复
            break;
		
        case CMD_ASK_VERSION_0X91:
			
            ScreenVersionRcv();  //版本号回复
            break;
		
        case CMD_ASK_FAULT_0X92:
			
            ScreenFaultRcv();    //故障记录回复
            break;
		
        case CMD_ASK_OPER_0X93:
			
            ScreenOperateRcv();  //操作记录回复
            break;
		
        case CMD_ASK_EXTH_0X94:
			
            ScreenStartRcv();    //启动记录回复
            break;
		
        case CMD_EXTH_CONF_0X95:               //预留灭火器配置信息
            break;
		
        case CMD_CLEAR_MESSG_0X96:
			
            ScreenClearRecord(buf); //清除
			break;
		
        case CMD_CHECK_TIME_0X97:
			
            ScreenCheckTime(buf);   //校准时间
			break;
		
        case CMD_ID_CONF_0X98:
			
            ScreenIdConfig(buf);    //ID配置
			break;
		
        case CMD_DEV_RESET_0X99:
			
            ScreenReset(buf);       //复位
			break;
		
        default:
          break;  
    }
}



static void SendRecBuf(uint8_t *Buf, uint8_t num)
{
	RS232_send(Buf , num);
	
	for(int i =0; i<num; i++)
	{
		DEBUG_LOG_INFO(DEBUG_LEVEL_2, "  %x  \n", Buf[i]);
	}

}




